package protocol

import (
	"fmt"
	"strings"
)

// PushOption represent the push options git pass to hook
type PushOption struct {
	Name  string
	Value string
}

// NegotiateResult struct
type NegotiateResult struct {
	Version            string
	ServerCapabilities map[string]bool
	HookCapabilities   map[string]bool
}

// ParseNegotiation parse version and push_options from payload
func ParseNegotiation(payload string) (*NegotiateResult, error) {
	if !strings.HasPrefix(payload, "version=") {
		return nil, fmt.Errorf("negotiate failed: invalid negotiations from receive-pack: %q", payload)
	}

	res := &NegotiateResult{
		ServerCapabilities: map[string]bool{},
		HookCapabilities:   map[string]bool{"push-options": false, "atomic": false},
	}
	splits := strings.SplitN(strings.TrimSuffix(payload, "\n"), "\000", 2)
	if len(splits) == 2 {
		for _, k := range strings.Split(splits[1], " ") {
			res.ServerCapabilities[k] = true
			if _, ok := res.HookCapabilities[k]; ok {
				res.HookCapabilities[k] = true
			}
		}
	}

	res.Version = strings.TrimPrefix(splits[0], "version=")
	if res.Version != "1" {
		return nil, fmt.Errorf("proc-receive: version %q is not supported", res.Version)
	}

	return res, nil
}

// GetHookCapabilities return hook's capabilities
func (n *NegotiateResult) GetHookCapabilities() string {
	var caps []string

	for k, v := range n.HookCapabilities {
		if v {
			caps = append(caps, k)
		}
	}

	return strings.Join(caps, " ")
}
